home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / security / doc / clippings / 910919-01 < prev    next >
Encoding:
Internet Message Format  |  1991-09-30  |  5.4 KB

  1. From: jmason2@gpu.utcs.utoronto.ca (Jamie Mason)
  2. Newsgroups: comp.unix.wizards
  3. Subject: Re: SUID shell scripts
  4. Summary: Why to *NEVER* *EVER* user set-uid scripts!
  5. Message-ID: <1991Sep19.125455.20375@gpu.utcs.utoronto.ca>
  6. Date: 19 Sep 91 12:54:55 GMT
  7. References: <1991Sep19.072220.206@dde.dk>
  8.  
  9. In article <1991Sep19.072220.206@dde.dk>, ct@dde.dk writes:
  10. >Some say that shell scripts with the Set-User-ID bit set (on systems
  11. >that allow it) are a security hazard. Why? If the script sets
  12. >up PATH and IFS, is it not safe?
  13.  
  14.     NO.
  15.  
  16.  
  17.     There are two reasons why not.  I'll tell you the easy one first.
  18. Assume that there is a set-uid script owned by root (more fun that way :-)
  19. called /local/bin/passwd (for instance).  Say that it is a bourne shell
  20. script, and so the first line is
  21.  
  22. #!/bin/sh
  23.  
  24.     Most shells will run as a login shell of the first character of
  25. their argv0 (first argument) starts with a '-'.  This is how login
  26. manages to give you a login shell.  It calls csh as '-csh'.  One of the
  27. things that a login shell does is read your .profile or .cshrc.
  28.  
  29.     On some systems, the shell is stupid enough to read and run
  30. $HOME/.profile even if it is running set-uid (effective uid != real uid).
  31.  
  32.     So on these systems, set-uid shell scripts are VERY VERY easy
  33. to break, and so are a big security hole from hell.  If you, or a
  34. cracker, felt like root access, you (or they) could try:
  35.  
  36. % cat > .profile
  37.     whoami  # to make sure.  id(1) would be fine as well.
  38.     cp /bin/sh $HOME/SU
  39.     chown root.wheel $HOME/SU
  40.     chmod 6755 $HOME/SU
  41. ^D
  42. % ln -s /local/bin/passwd -gotcha
  43. % ./-gotcha
  44. root
  45. % ls -l SU
  46. -rwsr-sr-x  1 root    wheel      106496 Oct 11  1990 SU
  47. % ./SU
  48. # whoami
  49. root
  50. # exit
  51.  
  52.     Now you have a set-uid root version of sh to play with.  It's
  53. setgid wheel too, just for fun.  :-)
  54.  
  55.  
  56.  
  57.     Now for the second security hole -- on almost all #! systems...
  58. When the kernel execs a file, it looks for a magic number in the first
  59. two bytes.  If the magic number is '#!', then it takes the next one or
  60. two tokens (up to 32 chars, usually), and tacks the full pathname of the
  61. script on as an argument.  So if /u/joeuser/foo stared with:
  62.  
  63. #!/bin/sh
  64.     then the kernel, in the process of loading this, would do:
  65. /bin/sh /u/joeuser/foo
  66.     Sh would have /u/joeuser/foo as $0 for the script.  If it was
  67. #!/bin/csh -f
  68.     then the kernel would execute
  69. /bin/csh -f /u/joeuser/foo
  70.  
  71.     The important thing to note here is that the shell re-opens the
  72. file for itself.  The kernel does not hand it an open file descriptor.
  73.  
  74.     So let's imagine that /local/bin/passwd example again.  If
  75. you ran /local/bin/passwd, then the kernel would set uid to root.  Then
  76.     it would call
  77. /bin/sh /local/bin/passwd
  78.     and /local/bin/passwd would do its stuff and exit.  No security hole
  79. here, unless /local/bin/passwd is a badly written script that does not
  80. set, for instance, $PATH.
  81.  
  82.     Ok.  But now lets try confusing things with a symlink, a
  83. little different from before...
  84.  
  85. % ln -s /local/bin/passwd mylink
  86. % cat > nasty_commands
  87.     whoami  # to make sure.  id(1) would be fine as well.
  88.     cp /bin/sh $HOME/SU
  89.     chown root.wheel $HOME/SU
  90.     chmod 6755 $HOME/SU
  91. ^D
  92. % ./mylink
  93.  
  94.     So the kernel stat()s $HOME/mylink.  stat() follows the link and
  95. sees the set-uid bit set and the owner being root on the other end of the
  96. link (i.e. /local/bin/passwd).  So the kernel sets uid to root.  Then it
  97. executes the following command:
  98.  
  99. /bin/sh /u/joeuser/mylink
  100.     The shell opens /u/joeuser/mylink.  The open() follows the link
  101. and opens the file at the other end (i.e. /local/bin/passwd) and executes
  102. the commands from it.  Still no security hole.
  103.  
  104.     But what if while the kernel was doing this, you did:
  105. % rm mylink; ln -s /u/joeuser/nasty_commands $HOME/mylink
  106.     Now when the kernel followed mylink, it found /local/bin/passwd.
  107. So it set-uid to root.  But my the time the SHELL followed mylink to
  108. open it, it finds $home/nasty_commands, which it executes...  As root.
  109.  
  110.     Now you will almost certainly NOT win such a race with the kernel
  111. >From the shell.  But you could do it in a C program.  You could
  112. fork, then nice the parent into the dirt (i.e. 20) on a loaded system.
  113. (If the system isn't loaded, load it.  Start some X applications :-)
  114. The parent can then exec() your symlink.
  115.     Meanwhile, in the child, you snip the symlink and make a new one.
  116. Most of the time, you will lose the race.  But not EVERY TIME.  And if
  117. the kernel loses the race JUST ONCE, then you win.  And you WIN BIG.
  118.  
  119.     Note that we put the same commands in nasty_commands as we put in
  120. ..profile in the last example.  I was trying to show what a cracker would
  121. do.  If someone was trying to crack your system, then that is the type
  122. of command they might issue.  They might put the suid sh in /tmp though,
  123. or somewhere else not traceable to them.  Since they now have root access,
  124. they can put it anywhere.  It may be lots of fun to find.  Once someone
  125. has broken root on your system JUST ONCE, it is very hard to get rid of
  126. them.  If they are smart, you may not even discover them.  If you do, you
  127. may not ever find all the little goodies they left around the system.
  128.  
  129.  
  130.  
  131.     So no, set-uid shell (or anything) scripts are not secure, ever.
  132.  
  133.     If it was only set-uid to a user, rather than root, or it was only
  134. set-gid to a special group, then the attacker will only be able to gain
  135. the privileges of the user or group rather than root.  And the 
  136. chown will have to come out of the attacker's script.  It might get
  137. replaced by a chgrp.
  138.  
  139.